package com.enjoy.adv.client;

import com.enjoy.adv.vo.MessageType;
import com.enjoy.adv.vo.MyHeader;
import com.enjoy.adv.vo.MyMessage;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.concurrent.ScheduledFuture;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by HP on 2019/7/18.
 * 心跳请求处理
 */
public class HeartBeatReqHandler extends ChannelInboundHandlerAdapter {
    private static final Log LOG = LogFactory.getLog(HeartBeatReqHandler.class);

    private volatile ScheduledFuture<?> heartBeat;

    //处理返回的消息
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        MyMessage message= (MyMessage) msg;
        //握手或者说登录成功 主动发送心跳消息
        if (message.getMyHeader()!=null&&message.getMyHeader().getType()==MessageType.LOGIN_RESP.getValue()){
            heartBeat=ctx.executor().scheduleAtFixedRate(
                    new HeartBeatTask(ctx),0,
                    5000, TimeUnit.MILLISECONDS);//5秒发送一次心跳
            ReferenceCountUtil.release(msg);
          //如果是心跳应答
        }else if (message.getMyHeader()!=null&&message.getMyHeader().getType()==MessageType.HEARTBEAT_RESP.getValue()){
            LOG.info("client receiver server heart beat message---->");
            ReferenceCountUtil.release(msg);
        }else {
            //如果是是其他报文传给后面handler
            ctx.fireChannelRead(msg);
        }
    }


    //心跳任务
    private class HeartBeatTask implements Runnable {
        private final ChannelHandlerContext ctx;
        //心跳计数，可用可不用，已经有超时处理机制
        private final AtomicInteger heartBeatCount;

        public HeartBeatTask(final ChannelHandlerContext ctx) {
            this.ctx = ctx;
            heartBeatCount = new AtomicInteger(0);
        }

        public void run() {
            MyMessage heatBeat = buildHeatBeat();
            ctx.writeAndFlush(heatBeat);
        }

        private MyMessage buildHeatBeat() {
            MyMessage message = new MyMessage();
            MyHeader myHeader = new MyHeader();
            myHeader.setType(MessageType.HEARTBEAT_REQ.getValue());
            message.setMyHeader(myHeader);
            return message;
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        if (heartBeat != null) {
            heartBeat.cancel(true);
            heartBeat = null;
        }
        ctx.fireExceptionCaught(cause);
    }
}
